
#include "glSkeletonFrame.h"
#include "skelanim/skeletonLoader.h"
#include "skelanim/motionLoader.h"

GLSkeletonFrame::GLSkeletonFrame(QWidget* parent, const QGLWidget* shareWidget, Qt::WFlags f)
   : OpenGLFrame(parent, shareWidget, f) {
   
   skeleton = 0;
   motion = 0;
   animator = 0;
   viewItemOff(FLOOR);
}

GLSkeletonFrame::~GLSkeletonFrame() {
   cout<<"::> ~GLSkeletonFrame()"<<endl;
   if (skeleton!=0)        delete skeleton;
   if (motion!=0)          delete motion;
   if (animator!=0)        delete animator;
   cout<<"::> ~GLSkeletonFrame() end"<<endl;
}

bool GLSkeletonFrame::loadSkeleton(const QString& filename) {
   
   QFileInfo fi(filename);
   QString extension = fi.suffix();
   
   GSkeleton *newskeleton = 0;
   if (extension == "asf") {
      SkeletonLoader sl;
      Skeleton *s = sl.load(filename.toStdString());
      newskeleton = new GSkeleton(*s);
      delete s;
   }
   else
      return false;
   
   if (newskeleton) {
      if (skeleton != 0) delete skeleton;
      skeleton = newskeleton;
      
      makeCurrent();
      cout<<"skeleton->nBones():::: "<<skeleton->nBones()<<endl;
      cout<<"skeleton->center(): "<<skeleton->center()<<endl;
      cout<<"skeleton->radius(): "<<skeleton->radius()<<endl;
      genWorldLimits(skeleton->center(), skeleton->radius());
      setGLview();
      
      cout<<":::::::::::::::::::::: "<<endl;
      
      sceneT.identity();
      return true;
   }
   return false;
}

bool GLSkeletonFrame::loadMotion(const QString& filename) {
   
   QFileInfo fi(filename);
   QString extension = fi.suffix();
   
   Motion *newmotion = 0;
   if (extension == "amc") {
      MotionLoader ml;
      newmotion = ml.load(filename.toStdString());
   }
   else
      return false;
   
   if (newmotion) {
      if (motion != 0) delete motion;
      motion = newmotion;
      cout<<"motion->getMotionSize(): "<<motion->getMotionSize()<<endl;
      
      if (animator != 0) delete animator;
      animator = new Animator(skeleton, motion);
      return true;
   }
   return false;
}

/// A simple opengl drawing callback
void GLSkeletonFrame::paintGL() {
   
   //~ setGLview();
   
   //~ glClearStencil(0x1);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   gluLookAt(cameye[0],cameye[1],cameye[2],camcenter[0],camcenter[1],camcenter[2],0,1,0);
   
   if (skeleton == 0) return;
   
   // Draw the 3D cursor
   const Number &scalefactor = (maxcoo[0]-mincoo[0])*(1.5/100);
   drawCursor3D(cursor3D, scalefactor);
   
   glMultMatrixf(&sceneT);
   
   // Draw the floor
   if ((viewitems_mask & FLOOR) == FLOOR)
      drawFloor();
   
   // Draw the skeleton
   //~ if ((viewitems_mask & MODELDEF) == MODELDEF) {
      glDrawSkeletonBones(skeleton);
   
      //~ glDrawSkeleton(animator->frame(currentFrame), meshrendermode_mask);
   //~ }
   
   if (interactionMode == SELECT_JOINTS_MODE) {
      glDrawSkeletonJoints(skeleton);
   }
   
   // Draw the shadow
   //~ if ((viewitems_mask & FLOOR) == FLOOR) {
      //~ glDisable(GL_LIGHTING);
      //~ glPushMatrix();
         //~ glMultMatrixf(shadowMatrix);
         //~ glColor4f(0.0f, 0.0f, 0.0f, 1.0);
         //~ glDrawSkeleton(skeleton, currentFrame, FLAT);
      //~ glPopMatrix();
      //~ glEnable(GL_LIGHTING);
   //~ }
   
   // FPS info
   //~ if ((viewitems_mask & INFO) == INFO)
      //~ fpsInfo();
}

void GLSkeletonFrame::mousePressEvent(QMouseEvent *event) {
   
   if (event->button() == Qt::LeftButton) {
      list<uint> selected;
      switch (interactionMode) {
         case VIEW_MODE: {
            
            break;
         }
         case SELECT_JOINTS_MODE: {
            cout<<"SELECT_JOINTS_MODE"<<endl;
            makeCurrent();
            // select a joint
            selection.begin(event->x(),height()-event->y());
            glDrawSkeletonJoints(skeleton);
            selection.end(selected);
            
            if (selected.empty()) idSelected = -1;
            else idSelected = selected.front();
            cout<<"xxx idSelected: "<<idSelected<<endl;
            
            break;
         }
      }
      glDraw();
   }
   else
      OpenGLFrame::mousePressEvent(event);
}

void GLSkeletonFrame::keyPressEvent(QKeyEvent *event) {
   
   if (event->key() == Qt::Key_Escape) {
      exit(0);
   }
   
   //~ switch(event->key()) {
      //~ case Qt::Key_Minus:
         //~ --currentFrame;
         //~ if (currentFrame < 0)
            //~ currentFrame = skeleton->getMotionSize() - 1;
         //~ break;
      //~ case Qt::Key_Plus:
         //~ ++currentFrame;
         //~ if (currentFrame >= skeleton->getMotionSize())
            //~ currentFrame = 0;
         //~ break;
   //~ }
   glDraw();
}

void GLSkeletonFrame::focusInEvent(QFocusEvent * event) {
   
   cout<<"GLSkeletonFrame::focusInEvent"<<endl;
}

void GLSkeletonFrame::focusOutEvent(QFocusEvent * event) {
   
   cout<<"GLSkeletonFrame::focusOutEvent"<<endl;
}

void GLSkeletonFrame::animateFrame(int animIndex) {
   
   if(animIndex<0)   currentFrame = 0;
   else              currentFrame = animIndex;
   
   animator->frame(currentFrame);
   glDraw();
}
